Skip to content

fix: MOS token device code fallback for macOS/Linux + remove dead AzureWebAppCreator#314

Merged
sellakumaran merged 2 commits intomainfrom
users/sellak/fix-mos-token-macos-platform-error
Mar 9, 2026
Merged

fix: MOS token device code fallback for macOS/Linux + remove dead AzureWebAppCreator#314
sellakumaran merged 2 commits intomainfrom
users/sellak/fix-mos-token-macos-platform-error

Conversation

@sellakumaran
Copy link
Copy Markdown
Contributor

  • MosTokenService: delegate to MsalBrowserCredential (useWam:false, custom authority) instead of calling AcquireTokenInteractive directly; eliminates PlatformNotSupportedException on macOS/Linux without a browser by inheriting MsalBrowserCredential's device code fallback
  • MsalBrowserCredential: add optional authority parameter to support government clouds (gcch/dod use login.microsoftonline.us) without defaulting to AzureCloudInstance.AzurePublic
  • MsalHelper: extract shared CreateDeviceCodeCallback to eliminate duplicate device code prompt display logic that existed in both MsalBrowserCredential and MosTokenService
  • MosTokenService: remove custom file-based token cache (mos-token-cache.json); MSAL's built-in persistent cache (DPAPI/Keychain/in-memory) replaces it with better security
  • MicrosoftGraphTokenProvider: raise LogDebug to LogWarning when MSAL fallback skipped due to missing clientAppId, making the silent failure path observable
  • AzureWebAppCreator: delete dead code -- CreateWebAppAsync was never called; setup infra creates web apps via az webapp create through CommandExecutor; remove from DI, all four command constructors, and both test files (23+11 constructor call sites cleaned up)

Closes #313

…reWebAppCreator

- MosTokenService: delegate to MsalBrowserCredential (useWam:false, custom authority)
  instead of calling AcquireTokenInteractive directly; eliminates PlatformNotSupportedException
  on macOS/Linux without a browser by inheriting MsalBrowserCredential's device code fallback
- MsalBrowserCredential: add optional authority parameter to support government clouds
  (gcch/dod use login.microsoftonline.us) without defaulting to AzureCloudInstance.AzurePublic
- MsalHelper: extract shared CreateDeviceCodeCallback to eliminate duplicate device code
  prompt display logic that existed in both MsalBrowserCredential and MosTokenService
- MosTokenService: remove custom file-based token cache (mos-token-cache.json); MSAL's
  built-in persistent cache (DPAPI/Keychain/in-memory) replaces it with better security
- MicrosoftGraphTokenProvider: raise LogDebug to LogWarning when MSAL fallback skipped
  due to missing clientAppId, making the silent failure path observable
- AzureWebAppCreator: delete dead code -- CreateWebAppAsync was never called; setup infra
  creates web apps via az webapp create through CommandExecutor; remove from DI, all four
  command constructors, and both test files (23+11 constructor call sites cleaned up)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@sellakumaran sellakumaran requested a review from a team as a code owner March 9, 2026 18:39
Copilot AI review requested due to automatic review settings March 9, 2026 18:39
@sellakumaran sellakumaran requested a review from a team as a code owner March 9, 2026 18:39
@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 9, 2026

⚠️ Deprecation Warning: The deny-licenses option is deprecated for possible removal in the next major release. For more information, see issue 997.

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a365 publish crashing on macOS/Linux with PlatformNotSupportedException during MOS token acquisition (issue #313) by making MosTokenService delegate to MsalBrowserCredential, which already has a device code fallback for headless environments. It also removes the dead AzureWebAppCreator class (never called in production) and refactors the shared device code prompt into a new MsalHelper helper.

Changes:

  • MosTokenService now delegates interactive auth to MsalBrowserCredential (with useWam:false, per-environment authority) instead of calling AcquireTokenInteractive directly; removes custom file-based token cache in favor of MSAL's built-in persistent cache
  • MsalBrowserCredential gains an optional authority parameter (for government clouds) and deduplicates device code prompt logic via the new MsalHelper.CreateDeviceCodeCallback
  • AzureWebAppCreator dead code deleted, along with its DI registration and all constructor call sites in commands and tests

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
MosTokenService.cs Delegates to MsalBrowserCredential; removes file-based token cache and direct MSAL calls
MsalBrowserCredential.cs Adds optional authority parameter; uses MsalHelper.CreateDeviceCodeCallback
MsalHelper.cs New shared helper with CreateDeviceCodeCallback to eliminate duplicate prompt logic
MicrosoftGraphTokenProvider.cs LogDebug → LogWarning for MSAL fallback skipped path
AzureWebAppCreator.cs Deleted (dead code)
Program.cs Removes AzureWebAppCreator DI registration and service resolution
SetupCommand.cs Removes AzureWebAppCreator parameter
AllSubcommand.cs Removes AzureWebAppCreator parameter
BlueprintSubcommand.cs Removes AzureWebAppCreator parameter
InfrastructureSubcommand.cs Removes AzureWebAppCreator parameter
MosTokenServiceCacheTests.cs Deleted (file-based cache removed)
MosTokenServiceTests.cs Removes [Collection] attribute no longer needed
MsalBrowserCredentialTests.cs Adds tests for authority parameter
SetupCommandTests.cs Removes _mockWebAppCreator from all test call sites
BlueprintSubcommandTests.cs Removes _mockWebAppCreator from all test call sites
Comments suppressed due to low confidence (1)

src/Microsoft.Agents.A365.DevTools.Cli/Services/MosTokenService.cs:84

  • The new catch (Exception ex) block catches all exceptions from MsalBrowserCredential.GetTokenAsync (including MsalAuthenticationFailedException with MSAL-specific error codes such as AADSTS650052, AADSTS50194, and invalid_grant) and swallows them, returning null. The PublishCommand.cs caller has specific catch (MsalServiceException) handlers for these error codes that provided tailored guidance; now those handlers are unreachable and users will only see the generic "Unable to acquire MOS token. Aborting publish." message regardless of the underlying cause.

If the MSAL-specific error codes need distinct guidance, consider extracting the per-code logic into MosTokenService (perhaps by catching MsalServiceException explicitly before the generic Exception) or re-throwing to let the caller handle them.

        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to acquire MOS token: {Message}", ex.Message);
            return null;

You can also share your feedback on Copilot code review. Take the survey.

…h blocks

- Add MsalHelperTests.cs covering both branches of CreateDeviceCodeCallback:
  logger path (LogInformation called) and null-logger path (Console.Error written)
- Move per-error-code MSAL guidance (AADSTS650052, AADSTS50194, invalid_grant)
  from PublishCommand into MosTokenService.LogMsalServiceError, where the auth
  concern belongs; catch MsalAuthenticationFailedException before catch Exception
- Remove 4 permanently unreachable catch(MsalServiceException) blocks from
  PublishCommand — MosTokenService never propagates MsalServiceException
- Fix stale invalid_grant guidance: remove reference to deleted mos-token-cache.json
- Remove now-unused 'using Microsoft.Identity.Client' from PublishCommand.cs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@sellakumaran sellakumaran merged commit 7596e25 into main Mar 9, 2026
8 checks passed
@sellakumaran sellakumaran deleted the users/sellak/fix-mos-token-macos-platform-error branch March 9, 2026 20:34
sellakumaran added a commit that referenced this pull request Mar 9, 2026
- Remove AzureWebAppCreator, IPrerequisiteRunner, IAzureEnvironmentValidator
  from all command signatures (SetupCommand, AllSubcommand, BlueprintSubcommand,
  InfrastructureSubcommand) per PR #314
- Update Program.cs and test files to match new signatures
- Retain PR #312 fixes: remove double logging in PrerequisiteRunner,
  fix \n in AppServiceAuthRequirementCheck resolution message,
  suppress pre-throw logging in ConfigService

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

a365 publish fails on macOS with PlatformNotSupportedException during MOS token acquisition

4 participants